package proxySourceColonSeparated

import (
	"bufio"
	"context"
	"fmt"
	"gitee.com/kaylee595/gkaylee/kerr"
	"gitee.com/kaylee595/proxy-pool/source"
	"github.com/imroc/req/v3"
	"net/url"
	"strings"
	"time"
)

type colonSeparated struct {
	url              string
	httpClient       *req.Client
	defaultSplitFunc bufio.SplitFunc
	defaultScheme    string
	defaultAuth      *url.Userinfo
	defaultExpire    time.Duration
}

func New(url string, opts ...Option) source.Fetcher {
	g := &colonSeparated{
		url:              url,
		httpClient:       req.DefaultClient(),
		defaultSplitFunc: bufio.ScanLines,
		defaultScheme:    "http",
		defaultExpire:    5 * time.Minute,
	}
	for _, opt := range opts {
		opt(g)
	}
	return g
}

func (c *colonSeparated) Fetch(ctx context.Context) ([]source.Node, error) {
	resp := c.httpClient.Get(c.url).EnableDump().Do(ctx)
	if resp.Err != nil {
		return nil, kerr.WrapTraceStack(resp.Err)
	}
	if !resp.IsSuccessState() {
		return nil, kerr.WrapTraceStack(fmt.Errorf("status code: %d, dump: %s", resp.StatusCode, resp.Dump()))
	}
	scanner := bufio.NewScanner(resp.Body)
	scanner.Split(c.defaultSplitFunc)
	rets := make([]source.Node, 0, 5)
	for scanner.Scan() {
		row := strings.TrimSpace(scanner.Text())
		if row == "" {
			continue
		}
		rowData := strings.Split(row, ":")
		if len(rowData) == 2 {
			rets = append(rets, &node{
				u: &url.URL{
					Scheme: c.defaultScheme,
					User:   c.defaultAuth,
					Host:   fmt.Sprintf("%s:%s", rowData[0], rowData[1]),
				},
				expiredTime: time.Now().Add(c.defaultExpire),
			})
		} else if len(rowData) == 4 {
			rets = append(rets, &node{
				u: &url.URL{
					Scheme: c.defaultScheme,
					User:   url.UserPassword(rowData[2], rowData[3]),
					Host:   fmt.Sprintf("%s:%s", rowData[0], rowData[1]),
				},
				expiredTime: time.Now().Add(c.defaultExpire),
			})
		}
	}
	return rets, nil
}
